#include <stdio.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <math.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>

#define LCD_DDR DDRB

#include "lcd.h"
#include "icon.h"
#include "buttons.h"
#include "backlight.h"
#include "pages.h"
#include "eeprom.h"
#include "can_avr.h"
#include "em36.h"
#include "body.h"


volatile uint8_t w25msTick = 0;
uint8_t w100msTask = 0;
uint16_t wTestModeAllowed;

bool bTestMode = false;

//diagnostics
uint8_t w25msOverrun = 0;


//	Enhanced delay-routine (wait) as as the standard delay routine (_delay_ms) is not able to delay
//	more than 17 ms maximum as of the used 8-bit-timer (depending on used crystal)
void delay_ms( uint16_t period )	 //delay routine (milliseconds)
{
	for( uint16_t i=0; i<=period; i++) _delay_ms(1);
}



/*********************************************************************************
** This is the 20ms tick
*********************************************************************************/
ISR (TIMER1_COMPA_vect) 	//timer1 match (compare A)
{
	if( w25msTick ) {
		w25msOverrun++;
	}
	else {
		w25msTick = 1;		// trigger the 25ms task
	}
}


void flash( void )
{
	static bool s = false;
	s = !s;
	LCD_Box(0,0,8,8,s?red:black);
}


void calculateIcons( void )
{
	ICON_show( ICON_LH, (BODY_flags & BODY_LH) );
	ICON_show( ICON_RH, (BODY_flags & BODY_RH) );
	ICON_show( ICON_WARNING, (BODY_flags & BODY_ERROR) );
	ICON_show( ICON_CHARGE, EM36_BATTERY_WARN );
	ICON_show( ICON_DOOR, (BODY_flags & BODY_DOOR) );
	ICON_show( ICON_FOG, (BODY_flags & BODY_FOG) );
	ICON_show( ICON_OILP, EM36_OILP_WARN );
	ICON_lights( BODY_LIGHTS );
}


int main(void)
{
	LCD_Init();

	DDRC = 0;			// all PORTD set to input
	DDRA = 1;			// A0 is an output
	DDRD = 1;			// D0 is an output
	PORTD = 0;			// low
	PORTC = 0xff;		// enable all pull ups
	// Port B7 = (OC0A / OC1C) dimmer, already set to output by LCD_Init()

	TCCR1A = 0;			// none of the output pins enabled, no PWM
	TCCR1B = 0x08		// CTC mode, 0 - OCRnA, TOVn set at max
 	       | 0x03;		// clock source = sysclk/64 (ie 250 to get 1ms)
	OCR1A = 6182;		// 25ms tick - seems to need 1% correction?
	TIMSK1 = 0x02;		// interrupts enabled, OC1EnA interrupt

	wTestModeAllowed = 5 * 40;	// 5 seconds (25ms ticks)

	BUTTONS_init( &butPage );
	BUTTONS_init( &butUp );
	BUTTONS_init( &butDn );

	EEPROM_init();
	CAN_init();		
	EM36_init();
	BODY_init();
	Orientation = Portrait180;
	LCD_Cls( black );
	
	PAGE_set( 0 );		// ActivePage is now set to zero (valid)

	//enable interrupts
	sei();

	while(1) {
		if( w25msTick ) {
			switch( w100msTask ) {
			case 00:
				EM36_task100ms();
				break;
				
			case 01:
				BODY_task100ms();		//checks for new CAN messages
				calculateIcons();
				PAGE_updateIcons();
				break;
				
			case 02:
				PAGE_updateActive();
				break;
				
			case 03:
				BODY_task100ms();		//checks for new CAN messages
				calculateIcons();
				PAGE_updateIcons();
				break;
			}

			w100msTask++;
			if(4 == w100msTask) w100msTask = 0;

			BUTTONS_check( &butPage, 	PINC & 0x01 );
			BUTTONS_check( &butDn, 		PINC & 0x10 );
			BUTTONS_check( &butUp, 		PINC & 0x04 );	

			if( wTestModeAllowed ) {
				wTestModeAllowed--;
				if( BUTTON_heldLonger( butUp, 40 ) && BUTTON_heldLonger( butDn, 40 ) ) {
					bTestMode = true;
				}
			}


			PAGE_handleButtons();
  			BACKLIGHT_Tick25ms();

			w25msTick = 0;
		}
	} 
}
